The present invention relates to the field of computer graphics. Many computer graphic images are created by mathematically modeling the interaction of light with a three dimensional scene from a given viewpoint. This process, called rendering, generates a two-dimensional image of the scene from the given viewpoint, and is analogous to taking a photograph of a real-world scene.
As the demand for computer graphics, and in particular for real-time computer graphics, has increased, computer systems with graphics processing subsystems adapted to accelerate the rendering process have become widespread. In these computer systems, the rendering process is divided between a computer's general purpose central processing unit (CPU) and the graphics processing subsystem. Typically, the CPU performs high level operations, such as determining the position, motion, and collision of objects in a given scene. From these high level operations, the CPU generates a set of rendering commands and data defining the desired rendered image or images. For example, rendering commands and data can define scene geometry, lighting, shading, texturing, motion, and/or camera parameters for a scene. The graphics processing subsystem creates one or more rendered images from the set of rendering commands and data.
Many graphics processing subsystems are highly programmable, enabling implementation of, among other things, complicated lighting and shading algorithms. In order to exploit this programmability, applications can include one or more graphics processing subsystem programs, which are executed by the graphics processing subsystem in parallel with a main program executed by the CPU. These graphics processing subsystem programs, often referred to as shader programs or shaders, can be used to define a set of operations to be performed on object geometry, object vertices, and/or fragments, which are groups of pixels or subpixels. Despite their name, shader programs are not confined to merely implementing shading and lighting algorithms and can be used to implement a variety of graphics algorithms, including geometry generation and modification, complex animations, motion and physics simulations, lighting and shading effects, reflections and refractions, texture mapping, and procedural texture generation.
Shader programs can be written in an assembly-like language specifically tailored to architecture of the graphics processing subsystem, or high-level languages such as Pixar's RenderMan, Nvidia's Cg, Microsoft's high-level shading language (HLSL), and the OpenGL Shading Language. Although simple visual effects can be implemented with shaders having only a few instructions, more complicated shaders can include hundreds or thousands of instructions.
As developers create shaders with increasing size and complexity, tuning the performance of shaders and eliminating errors becomes more difficult. In addition to the complexity arising from the increased length of shaders, a single shader can operate on thousands or millions of geometric primitives or fragments; however, in many cases, only some of geometric primitives or fragments will manifest obvious signs of errors or poor performance. The shader developer must then try to isolate the affected primitives or fragments and their associated instances of the shader in order to identify the problem with the shader program.
Conventional debugging and profiling applications provide developers with the ability to analyze programs running on conventional CPUs. Many debugging and profiling applications enable developers to set breakpoints with a program. Program execution stops upon reaching the breakpoint. The debugger application enables developers to examine and optionally alter the values of variables and data in registers and memory, step through program execution one instruction at a time, or resume program execution. Profiling applications enable developers to identify the portions of the program that require the most time to execute.
There are several obstacles to providing similar debugging and profiling capabilities for shaders executed by a graphics processing subsystem. Graphics processing subsystems typically process rendering instructions and data in a very long processing pipeline. There may be hundreds or thousands of internal registers as well as internal memory deep within this pipeline that is typically not accessible outside of the graphics processing subsystem. This prevents debugging and profiling applications from retrieving and/or altering data in these locations. Furthermore, modifying the graphics processing subsystem to provide additional input and output connections for enabling external access to these registers and memories is often impractical if not impossible.
Additionally, graphics processing subsystems often process many fragments or primitives in parallel, each with its own instance of a shader program. Upon reaching a breakpoint in one shader program, stopping its execution while allowing other shader programs to continue can create problems with synchronization and data corruption. These problems can be exacerbated if the remaining running shader programs reach their own breakpoints while a first shader program is still stopped.
Once the developer has finished analyzing a shader program at a breakpoint, there is no way for the debugging or profiling application to restore the state of the graphics processing subsystem prior to the breakpoint and to resume normal operation. Furthermore, typical graphics processing subsystems do not have the capability to step through shader instructions one at a time, referred to as single-stepping, to enable developers to observe changes in program data values.
It is therefore desirable for a system and method to provide debugging and profiling capabilities for shader programs being executed by a graphics processing subsystem. It is further desirable for the system and method to provide these capabilities using existing resources of the graphics processing subsystem and without the need for additional data inputs and outputs. It is also desirable for the system and method to prevent conflicts and errors arising from multiple instances of shader programs executed in parallel by the graphics processing subsystem. It is desirable for the system and method to allow resuming normal execution of shader programs after a breakpoint and to enable developers to single-step through shader program instructions. It is desirable to minimize any additional performance burden on the graphics processing subsystem during debugging and profiling operations.